﻿using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NCrontab;
using System.Collections.Concurrent;

namespace SEGIService
{
    public class ScheduledTaskService : BackgroundService
    {
        private readonly ILogger<ScheduledTaskService> _logger;
        private readonly IEnumerable<SEGIIScheduledTask> _tasks;
        private readonly ConcurrentDictionary<string, CrontabSchedule> _schedules = new();
        private readonly ConcurrentDictionary<string, DateTime> _nextOccurrences = new();

        public ScheduledTaskService(
            ILogger<ScheduledTaskService> logger,
            IEnumerable<SEGIIScheduledTask> tasks)
            {
            _logger = logger;
            _tasks = tasks;

            // 初始化任务调度
            foreach (var task in tasks)
            {
                _schedules.TryAdd(task.GetType().FullName!, CrontabSchedule.Parse(task.Schedule));
                _nextOccurrences.TryAdd(task.GetType().FullName!,
                    _schedules[task.GetType().FullName!].GetNextOccurrence(DateTime.Now));
            }
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _logger.LogInformation("定时任务服务已启动");

            while (!stoppingToken.IsCancellationRequested)
            {
                var now = DateTime.Now;

                // 检查所有任务是否到执行时间
                foreach (var task in _tasks)
                {
                    var taskType = task.GetType().FullName!;
                    if (_nextOccurrences[taskType] <= now)
                    {
                        try
                        {
                            _logger.LogInformation($"开始执行任务: {taskType}");
                            await task.ExecuteAsync(stoppingToken);

                            // 更新下一次执行时间
                            _nextOccurrences[taskType] =
                                _schedules[taskType].GetNextOccurrence(DateTime.Now);

                            _logger.LogInformation($"任务 {taskType} 执行完成，下次执行时间: {_nextOccurrences[taskType]}");
                        }
                        catch (Exception ex)
                        {
                            _logger.LogError(ex, $"任务 {taskType} 执行失败");
                        }
                    }
                }

                // 等待1秒后再次检查
                await Task.Delay(1000, stoppingToken);
            }

            _logger.LogInformation("定时任务服务已停止");
        }
    }
}
